package com.googlecode.bip.entity.impl;

import java.io.Serializable;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import com.googlecode.bip.entity.IQuestion;
import com.googlecode.bip.entity.IllegalValueException;

/**
 * Default implementation of {@link IQuestion}
 */
public class Question implements IQuestion, Serializable
{
    private static final long serialVersionUID = 3L;

    private int idquestion;
    private String idlocal;
    private String name;
    private String description;
    private int parentidtopic;
    private int order;
    private int minvalue;
    private int maxvalue;
    private int defaultvalue;
    private int isactive;
    private boolean isPrivate;
    private Map<Integer,String> textValues = new HashMap<Integer,String>();


    /**
     * Create a NOT initialized Question
     */
    public Question()
    {
    }

    /**
     * Create a shadow copy of giving Question
     *
     * @param o Question to clone
     */
    public Question( final Question o )
    {
        this.idquestion         = o.idquestion;
        this.idlocal            = o.idlocal;
        this.name               = o.name;
        this.description        = o.description;
        this.parentidtopic      = o.parentidtopic;
        this.order              = o.order;
        this.minvalue           = o.minvalue;
        this.maxvalue           = o.maxvalue;
        this.defaultvalue       = o.defaultvalue;
        this.isactive           = o.isactive;
        this.isPrivate          = o.isPrivate;

        for( Entry<Integer,String> entry : o.textValues.entrySet() ) {
            this.textValues.put( entry.getKey(), entry.getValue() );
            }
    }

    /**
     * Set values from {@link ResultSet}
     * @param rSet
     * @return
     * @throws SQLException
     */
    final
    public Question set( final ResultSet rSet ) throws SQLException
    {
        this.idquestion      = rSet.getInt( "idquestion" );
        this.idlocal         = rSet.getString( "idlocal" );
        this.name            = rSet.getString( "questionname" );
        this.description     = rSet.getString( "questiondescription" );
        this.parentidtopic   = rSet.getInt( "idtopic" );
        this.order           = rSet.getInt( "order" );
        this.minvalue        = rSet.getInt( "minvalue" );
        this.maxvalue        = rSet.getInt( "maxvalue" );
        this.defaultvalue    = rSet.getInt( "defaultvalue" );
        this.isactive        = rSet.getInt( "isactive" );
        this.textValues.clear();

        return this;
    }

    /**
     * Set text translation for valid values
     *
     * @param value specified value
     * @param text  text translation for specified value
     * @return this object for initialization chaining
     * @throws IllegalValueException if value is not in valid range
     */
    final
    public Question set( final int value, final String text )
        throws IllegalValueException
    {
        if( value < this.minvalue ) {
            throw new IllegalValueException( value, this.minvalue, this.maxvalue );
            }
        if( value > this.maxvalue ) {
            throw new IllegalValueException( value, this.minvalue, this.maxvalue );
            }
        this.textValues.put( value, text );

        return this;
    }

    @Override
    final
    public int getIdQuestion()
    {
        return idquestion;
    }

    // Charless: REQUIRED for JSON to work !
    @Override
    public void setIdQuestion( final int idquestion )
    {
        this.idquestion = idquestion;
    }

    // Charless: REQUIRED for JSON to work !
    @Override
    public void setIdLocal(String idlocal)
    {
        this.idlocal = idlocal;
    }

    @Override
    final
    public String getIdLocal()
    {
        return idlocal;
    }

    @Override
    final
    public String getName()
    {
        return name;
    }

    @Override
    final
    public void setName( final String name )
    {
        this.name = name;
    }

    @Override
    final
    public String getDescription()
    {
        return description;
    }

    @Override
    final
    public void setDescription( final String description )
    {
        this.description = description;
    }

    @Override
    final
    public int getParentIdTopic()
    {
        return parentidtopic;
    }

    // Charless: REQUIRED for JSON to work !
    @Override
    public void setParentIdTopic( final int parentidtopic )
    {
        this.parentidtopic = parentidtopic;
    }

    @Override
    final
    public int getOrder()
    {
        return order;
    }

    @Override
    final
    public void setOrder( final int order )
    {
        this.order = order;
    }

    @Override
    final
    public int getMinValue()
    {
        return minvalue;
    }

    // Charless: REQUIRED for JSON to work !
    @Override
    public void setMinValue( final int minvalue )
    {
        this.minvalue = minvalue;
    }

    @Override
    final
    public int getMaxValue()
    {
        return maxvalue;
    }

    // Charless: REQUIRED for JSON to work !
    @Override
    public void setMaxValue( final int maxvalue )
    {
        this.maxvalue = maxvalue;
    }

    @Override
    final
    public int getDefaultValue()
    {
        return defaultvalue;
    }

    // Charless: REQUIRED for JSON to work !
    @Override
    public void setDefaultValue( final int defaultvalue )
    {
        this.defaultvalue = defaultvalue;
    }

    @Override
    final
    public int getIsActive()
    {
        return isactive;
    }

    @Override
    final
    public void setIsActive( final int isactive )
    {
        this.isactive = isactive;
    }

    @Override
    public boolean isPrivate()
    {
        return this.isPrivate;
    }

    @Override
    public void setPrivate( boolean isPrivate )
    {
        this.isPrivate = isPrivate;
    }


    @Override
    public String getTextValue( final int value ) throws IllegalValueException
    {
        if( value < this.minvalue ) {
            throw new IllegalValueException( value, this.minvalue, this.maxvalue );
            }
        if( value > this.maxvalue ) {
            throw new IllegalValueException( value, this.minvalue, this.maxvalue );
            }
        return this.textValues.get( new Integer( value ) );
    }

    // Charless: REQUIRED for JSON to work !
    @Override
    public List<List<Object>> getListTextValues() {
        ArrayList<List<Object>> res = new ArrayList<List<Object>>();
        for (int i=this.getMinValue();i<=this.getMaxValue();i++) {
            try {
                ArrayList<Object> valueText = new ArrayList<Object>();
                valueText.add(i);
                valueText.add(this.getTextValue(i));
                res.add(valueText);
            }
            catch(Exception e) {
                // Ignore value
            }
        }
        return res;
    }

    // Charless: REQUIRED for JSON to work !
    @Override
    public void setListTextValues(List<List<Object>> textValues) {
        for (List<Object> o: textValues) {
            Integer value = Integer.class.cast(o.get(0));
            String description = String.class.cast(o.get(1));
            this.textValues.put(value, description);
        }
    }


    /* (non-Javadoc)
     * @see java.lang.Object#toString()
     */
    @Override
    public String toString()
    {
        return "Question [idquestion=" + idquestion
                + ", idlocal=" + idlocal
                + ", name=" + name
                + ", description=" + description
                + ", parentidtopic=" + parentidtopic
                + ", order=" + order
                + ", minvalue=" + minvalue
                + ", maxvalue=" + maxvalue
                + ", defaultvalue=" + defaultvalue
                + ", isactive=" + isactive
                + ", isPrivate=" + isPrivate
                + ", textValues=" + textValues
                + "]";
    }

    /* (non-Javadoc)
     * @see java.lang.Object#hashCode()
     */
    @Override
    public int hashCode()
    {
        final int prime = 31;
        int result = 1;
        result = prime * result + defaultvalue;
        result = prime * result
                + ((description == null) ? 0 : description.hashCode());
        result = prime * result + ((idlocal == null) ? 0 : idlocal.hashCode());
        result = prime * result + idquestion;
        result = prime * result + (isPrivate ? 1231 : 1237);
        result = prime * result + isactive;
        result = prime * result + maxvalue;
        result = prime * result + minvalue;
        result = prime * result + ((name == null) ? 0 : name.hashCode());
        result = prime * result + order;
        result = prime * result + parentidtopic;
        result = prime * result
                + ((textValues == null) ? 0 : textValues.hashCode());
        return result;
    }

    /* (non-Javadoc)
     * @see java.lang.Object#equals(java.lang.Object)
     */
    @Override
    public boolean equals( Object obj )
    {
        if( this == obj ) {
            return true;
        }
        if( obj == null ) {
            return false;
        }
        if( !(obj instanceof Question) ) {
            return false;
        }
        Question other = (Question)obj;
        if( defaultvalue != other.defaultvalue ) {
            return false;
        }
        if( description == null ) {
            if( other.description != null ) {
                return false;
            }
        } else if( !description.equals( other.description ) ) {
            return false;
        }
        if( idlocal == null ) {
            if( other.idlocal != null ) {
                return false;
            }
        } else if( !idlocal.equals( other.idlocal ) ) {
            return false;
        }
        if( idquestion != other.idquestion ) {
            return false;
        }
        if( isPrivate != other.isPrivate ) {
            return false;
        }
        if( isactive != other.isactive ) {
            return false;
        }
        if( maxvalue != other.maxvalue ) {
            return false;
        }
        if( minvalue != other.minvalue ) {
            return false;
        }
        if( name == null ) {
            if( other.name != null ) {
                return false;
            }
        } else if( !name.equals( other.name ) ) {
            return false;
        }
        if( order != other.order ) {
            return false;
        }
        if( parentidtopic != other.parentidtopic ) {
            return false;
        }
        if( textValues == null ) {
            if( other.textValues != null ) {
                return false;
            }
        } else if( !textValues.equals( other.textValues ) ) {
            return false;
        }
        return true;
    }
}
